package org.opendream.roti.service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import org.opendream.roti.domain.NameEntityOld;
import org.opendream.roti.domain.TrieNode;
import org.opendream.roti.domain.NameEntityOld.EntityType;

public class NameEntityService {

    private TrieNode root = new TrieNode((char)0);
	
	public NameEntityService() {		
		loadNames(EntityType.PEOPLE, "people.txt");
		loadNames(EntityType.PLACE, "places.txt");
		loadNames(EntityType.ORGANIZATION, "organizations.txt");				
	}
	
	public List<NameEntityOld> extract(String txt) {
	    return new TrieNodeIterator(root, txt).extract();
	}
	
	private void loadNames(EntityType type, String resourceName) {
		InputStream namesStream = getClass().getResourceAsStream("/nameentities/" + resourceName);
		try {
			BufferedReader in = new BufferedReader(new InputStreamReader(namesStream, "UTF-8"));
			String line;
			while ((line = in.readLine()) != null) {
				root.insert(line, 0, type);				
			}
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

class TrieNodeIterator {
    private TrieNode root;
    private String txt;

    public TrieNodeIterator(TrieNode root, String txt) {
        this.root = root;
        this.txt = txt;
    }
    
    public List<NameEntityOld> extract() {
        ArrayList<NameEntityOld> list = new ArrayList<NameEntityOld>();
        TrieNode curNode = root;
        int startIdx = 0, endIdx = 0;
        int cnt = txt.length();
        while (endIdx < cnt) {
            char c = txt.charAt(endIdx);
            
            if (curNode.type != null) { // end of word
                list.add(new NameEntityOld(curNode.getWord(), curNode.type) );
                startIdx = endIdx;
                curNode = root;
            }
            
            TrieNode tmp = curNode.children.get(c);
            if (tmp == null) {
                tmp = root;
                endIdx = startIdx++;                
            }
                        
            curNode = tmp;
            endIdx++;                        
        }
        if (curNode.type != null) { // end of word
            list.add(new NameEntityOld(curNode.getWord(), curNode.type) );
        }
        
        return list;
    }
}